package dev.ideas.funkyj.group;

import dev.ideas.funkyj.function.F;
import dev.ideas.funkyj.function.F2;
import dev.ideas.funkyj.sequence.Sequence;
import dev.ideas.funkyj.tuple.Single;

import java.util.Iterator;

/**
 */
public class Group3<G3, G2, G1, T> extends _Group.Node<G3, Group2<G2, G1, T>, T> {
    private final F<T, G3> f3;
    private final F<T, G2> f2;
    private final F<T, G1> f1;

    public Group3(final Iterator<T> iterator, final F<T, G3> f3, final F<T, G2> f2, final F<T, G1> f1) { super(iterator); this.f1 = f1; this.f2 = f2; this.f3 = f3; }
    Group3(final _Group.Root<T> root, final F<T, G3> f3, final F<T, G2> f2, final F<T, G1> f1) { super(root); this.f1 = f1; this.f2 = f2; this.f3 = f3; }

    @Override G3 key(T t) { return f3.apply(t); }
    @Override Group2<G2, G1, T> create() { return new Group2<G2, G1, T>(root, f2, f1); }

    public Group2<G2, G1, T> select(final G3 g3) { return get(g3); }
    public Group1<G1, T> select(final G3 g3, final G2 g2) { return select(g3).select(g2); }
    public Sequence<T> select(final G3 g3, final G2 g2, final G1 g1) { return select(g3).select(g2, g1); }

    //
    /* to reduce */
    public Group<G3, Group<G2, Group<G1, Single<T>>>> to(final F2<T, T, T> f) {
        return new Group<G3, Group<G2, Group<G1, Single<T>>>>() {
            @Override public Group<G2, Group<G1, Single<T>>> select(G3 g3) {
                return Group3.this.select(g3).to(f);
            }
        };
    }
}